#pragma once
#include "sfm_basic.h"
#include <opencv2/opencv.hpp>
#include <Eigen/Core>
#include <vector>

namespace ville3d {
class FeatureMatcher {
 public:
  bool KnnMatchBetweenKeyFrames(std::shared_ptr<View> view1,
                                std::shared_ptr<View> view2,
                                std::vector<cv::DMatch>& matches,
                                float nnratio);

  bool EpipolarMatchBetweenKeyFrames(std::shared_ptr<View> view1,
                                     std::shared_ptr<View> view2,
                                     std::vector<cv::DMatch>& matches,
                                     float nnratio, double errorTh);

    // Computes the Hamming distance between two ORB descriptors
  int DescriptorDistance(const cv::Mat& a, const cv::Mat& b);

private:
  bool line_to_endPoints(const Eigen::Vector3d& line, int W, int H,
                         Eigen::Vector2d& x0);

  unsigned int pix_to_bucket(const Eigen::Vector2i& x, int W, int H);

  Eigen::Matrix3d ComputeF12(std::shared_ptr<View> view1,
                             std::shared_ptr<View> view2);

  bool GetEpipolarLine(const cv::KeyPoint& kp1, const Eigen::Matrix3d& F12,
                       double& a, double& b, double& c);

  double ComputeDisPtToLine2D(const Eigen::Vector2d& pt, double a, double b,
                              double c);

};
}  // namespace ville3d
